<template>
  <div class="employees-container">
    <div class="app-container">
      <div>
        <!-- 通用工具栏组件使用 -->
        <page-tools>
          <!-- 自定义左侧内容 -->
          <template v-slot:slot-left>
            <span>共19条记录</span>
          </template>

          <!-- 自定义右侧内容 -->
          <template #slot-right>
            <!-- 挂载自定义指定, 按钮功能权限设置 -->
            <el-button v-power="'export'" type="danger" size="small" @click="exportExcelFn">
              普通Excel导出
            </el-button>
            <el-button size="small" type="info">
              复杂表头Excel导出
            </el-button>
            <!-- 挂载自定义指定, 按钮功能权限设置 -->
            <el-button v-power="'import'" type="success" size="small" @click="$router.push('/excel')">excel导入</el-button>
            <el-button type="primary" size="small" @click="showDialog = true">新增员工</el-button>
          </template>
        </page-tools>
      </div>
      <!-- 下方的表格 -->
      <el-card style="margin-top: 10px;">
        <el-table :data="employeesList" border>
          <el-table-column sortable label="序号" type="index" />
          <el-table-column sortable label="姓名" prop="username" />
          <el-table-column sortable label="头像" prop="staffPhoto">
            <template v-slot="scope">
              <!-- image组件内定义的属性就是src 并且有一个默认图片 -->
              <image-holder class="staffPhoto" :src="scope.row.staffPhoto" />
            </template>
          </el-table-column>
          <el-table-column sortable label="手机号" prop="mobile" />
          <!-- :formatter="formatWorkNumberFn" 用不上了 -->
          <el-table-column sortable label="工号" :sort-method="sortWorkNumberFn" prop="workNumber" />
          <el-table-column sortable label="聘用形式">
            <!--要使用方法转换 不能用prop了，使用作用域插槽 -->
            <template v-slot="scope">
              <span> {{ formatEmployeeFn(scope.row.formOfEmployment) }} </span>
            </template>
          </el-table-column>
          <el-table-column sortable label="部门" prop="departmentName" />
          <el-table-column sortable label="入职时间" prop="timeOfEntry" />
          <el-table-column sortable label="操作" width="280">
            <!-- 作用域插槽必须用v-slot="scope" scope会获取到当前组件上的所有信息 存在row对象里-->
            <template v-slot="scope">
              <!-- 跳转传参传该员工的id，因为进到员工详情页，需要发送请求，请求params就是id -->
              <el-button type="text" size="small" @click="$router.push(`/employees/detail?id=${scope.row.id}`)">查看</el-button>
              <el-button type="text" size="small" @click="setEmp(scope.row.id)">分配角色</el-button>
              <el-button type="text" size="small" @click="delEmpFn(scope.row.id)">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
        <!-- 分页组件 -->
        <el-row type="flex" justify="center" align="middle" style="height: 60px">
          <!-- 分页区域 -->
          <el-pagination
            :current-page="query.page"
            :page-sizes="[10, 15, 20, 25]"
            :page-size="query.size"
            layout="total, sizes, prev, pager, next, jumper"
            :total="total"
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
          />
        </el-row>
      </el-card>

      <!-- 新增员工弹窗 -->
      <el-dialog title="新增员工" :visible.sync="showDialog" @close="dialogCloseFn">
        <emp-form
          ref="empForm"
          :tree-data="treeData"
          @close="formCloseFn"
          @add-emp="addEmpFn"
        />
      </el-dialog>

      <el-dialog title="分配角色" :visible.sync="showRoleDialog" @close="cancleDialog">
        <AssignRoleDialog
          ref="roleDialog"
          :role-list="roleList"
          @close="cancleDialog"
          @confirm="confirmFn"
        />
      </el-dialog>
    </div>
  </div>
</template>

<script>
// 字符串 和字符串数字/字母对比，从左侧按位比较ASCII码
// 字符串和数字比较，会转成数字比较
import { getEmployeeListAPI, departmentsListAPI, addEmployeeAPI, delEmployeeAPI, getRolesAPI, getUserDetailByIdAPI, assignRolesAPI } from '@/api'
import { transTree } from '@/utils'
import EmpForm from './components/empForm.vue'
import AssignRoleDialog from './components/assignRoleDialog.vue'
export default {
  name: 'Employees',
  components: {
    EmpForm,
    AssignRoleDialog
  },
  data() {
    return {
      query: {
        page: 1, // 页码
        size: 10 // 每页条数
      },
      employeesList: [], // 员工列表
      total: 0, // 数据总条数
      showDialog: false, // 添加员工组件的展示
      treeData: [], // 部门列表数据
      showRoleDialog: false, // 分配角色弹窗显示
      employeeId: '', // 传给分配角色组件里的id
      roleList: [] // 角色列表 要传给分配角色的组件
    }
  },
  created() {
    // 员工列表
    this.getEmployeeListFn()
    // 部门列表 查看员工详情页面
    this.getDepartmentsListFn()
    // 角色列表
    this.getRolesFn()
  },
  methods: {
    // 获取员工列表
    async getEmployeeListFn() {
      const res = await getEmployeeListAPI(this.query)
      // console.log(res)
      this.employeesList = res.data.rows
      this.total = res.data.total
      // console.log(res.data.rows)
    },
    // 每页显示的条数发生改变时触发
    handleSizeChange(newSize) {
      this.query.size = newSize
      this.getEmployeeListFn()
    },

    // 当前页面发生改变时触发
    handleCurrentChange(newPage) {
      this.query.page = newPage
      this.getEmployeeListFn()
    },
    // 有些聘用形式是1 或者没有 需要用方法转化一下
    formatEmployeeFn(str) {
      // 如果传入的是'1' 或者正式 返回正式
      if (String(str) === '1' || str === '正式') {
        return '正式'
      } else { // 其他的情况都是非正式
        return '非正式'
      }
    },
    // // 工号 - 格式化 用于格式化指定列的值，接受一个Function
    // formatterFn(row, column) {
    //   return row.workNumber * 1
    // },
    // 工号 - 自定义排序过程
    // 必须触发工号的-排序点击箭头事件才会执行
    // 类似数组.sort()方法
    sortWorkNumberFn(a, b) {
      // return 小于0, a在b前面 , 从小到大
      // return 大于0, b在a前面,  从大到小
      // console.log(a)
      // console.log(b)
      // 打印得知 a和b是两个对象(数组里相邻的2个元素)

      return a.workNumber - b.workNumber
    },
    // 表单-确定和取消按钮-弹窗关闭
    formCloseFn() {
      this.showDialog = false
    },
    // 获取部门列表
    async getDepartmentsListFn() {
      const res = await departmentsListAPI()
      // 获取到的是扁平数据 要用transTree方法啊转化为树状结构
      this.treeData = transTree(res.data.depts, '')
      // console.log(this.treeData)
    },
    // 新增员工事件
    async addEmpFn(formData) {
      const res = await addEmployeeAPI(formData)
      // console.log(res)
      if (!res.success) this.$message.error(res.message)
      this.$message.success(res.message)
      this.showDialog = false
      this.getEmployeeListFn() // 重新获取
    },
    // 获取角色列表
    async getRolesFn() {
      const res = await getRolesAPI()
      this.roleList = res.data.rows
    },

    // 弹窗被关闭-》检测到的事件
    dialogCloseFn() {
      setTimeout(() => {
        this.$refs.empForm.$refs.addForm.resetFields()
      })
    },

    // // 点击导出excel事件
    // exportExcelFn() {
    //   // this.downloadLoading = true
    //   import('@/vendor/Export2Excel').then(excel => {
    //     // 目标：1、把tHeader换成中文版的
    //     //      2、把data换成数组套数组的形式，内容是对应的数据
    //     const map = {
    //       'id': '编号',
    //       'password': '密码',
    //       'mobile': '手机号',
    //       'username': '姓名',
    //       'timeOfEntry': '入职日期',
    //       'formOfEmployment': '聘用形式',
    //       'correctionTime': '转正日期',
    //       'workNumber': '工号',
    //       'departmentName': '部门',
    //       'staffPhoto': '头像地址'
    //     }
    //     // 1、先做第一个小目标（换中文）：员工列表数组里就能拿到员工数据  该数组里每个对象的key都一致，所以就拿第一个出来吧
    //     const rowArr = this.employeesList
    //     const rowObj = this.employeesList[0]
    //     // Object.keys(对象) 把所有key取出来形成一个新数组
    //     const EnglishHeaders = Object.keys(rowObj)
    //     // 把map数组里的中文值全放到了tHeader里 形成一个数组
    //     const tHeader = EnglishHeaders.map(key => map[key])

    //     // 2、小目标2
    //     // Object.values() 作用:把()里对象的值，收集成一个数组返回在原地 map再返回一个数组，就形成了 数组套数组
    //     const data = rowArr.map(obj => Object.values(obj))
    //     // const data = [['1', '标题', '作者', '读取', '日期']]
    //     // const list = this.list
    //     // const data = this.formatJson(filterVal, list) // 这个是别人的代码自己用不了
    //     excel.export_json_to_excel({
    //       header: tHeader,
    //       data,
    //       filename: '1.xlsx',
    //       autoWidth: true,
    //       bookType: 'xlsx'
    //     })
    //     // this.downloadLoading = false
    //   })
    // },

    // 精讲 表格导出 - 点击事件
    exportExcelFn() {
      // this.downloadLoading = true
      import('@/vendor/Export2Excel').then(excel => {
        // 为了跟页面上的一模一样
        // 因为我们用的是后台返回的数组, 页面单独处理过的
        // 在这里我们也要单独处理, 数组要按照顺序(思路有很多)
        /**
         * {
            'id': '序号'
           }
           这样写 只能是key和value对应, 没法加第三方需求
         */
        // 1. 数据映射数组(顺序)-8列和页面一样
        const arr = [
          {
            key: 'id',
            name: '序号'
          },
          {
            key: 'username',
            name: '姓名'
          },
          {
            key: 'staffPhoto',
            name: '头像'
          },
          {
            key: 'mobile',
            name: '手机号'
          },
          {
            key: 'workNumber',
            name: '工号'
          },
          {
            key: 'formOfEmployment',
            name: '聘用形式'
          },
          {
            key: 'departmentName',
            name: '部门'
          },
          {
            key: 'timeOfEntry',
            name: '入职日期'
          }
        ]

        // 1、先做第一个小目标（换中文的表头）：员工列表数组里就能拿到员工数据  该数组里每个对象的key都一致，所以就拿第一个出来吧
        const tHeader = arr.map(item => item.name)
        // 2、拿到员工数据
        const rowArr = this.employeesList
        // 我们把arr里所有key(英文)->统一出来
        const keyArr = arr.map(item => item.key)

        const data = rowArr.map((obj, index) => {
          // 按照顺序, 再从obj里取值, 形成一个新的 值数组
          const values = keyArr.map(enKey => {
            // id要改成index的值
            if (enKey === 'id') {
              return index
            } else if (enKey === 'formOfEmployment') { // 聘用形式
              // 如果聘用形式传的是'1' 或者正式 返回正式
              if (String(obj[enKey]) === '1' || obj[enKey] === '正式') {
                return '正式'
              } else { // 其他的情况都是非正式
                return '非正式'
              }
            } else { // 其他的正常取值
              return obj[enKey]
            }
          }) // values数组是 ['id值', '管理员', ....]8个值

          return values // 让当前278行map收集小数组
        })
        // console.log(data)
        excel.export_json_to_excel({
          header: tHeader, // 导出数据的表头
          data, // 导出的具体数据
          filename: 'employee-data', // 导出文件名
          autoWidth: true, // 单元格是否要自适应宽度
          bookType: 'xlsx' // 导出文件类型
        })
        // this.downloadLoading = false
      })
    },
    // 删除员工方法
    async delEmpFn(id) {
      const delRes = await this.$confirm('此操作将永久删除该角色, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).catch(err => err)

      if (delRes === 'cancel') return
      const res = await delEmployeeAPI(id)
      if (res.success) this.$message.success(res.message)

      // 如果删除了当前页最后一条数据会显示数据为空，本应该自动显示第一页的数据
      if (this.employeesList.length === 1) { // 如果当前页只剩最后一条数据，删除后，让页码-1
        this.query.page--
        // 如果只剩第一页的最后一条数据 就让页码始终为1
        if (this.query.page <= 1) this.query.page = 1
      }

      // 重新获取数据
      this.getEmployeeListFn()
    },
    // 角色分配 - 弹窗
    async setEmp(id) {
      this.employeeId = id
      this.showRoleDialog = true
      // 获取对应员工的详细信息（里面包含角色id列表 ）
      const res = await getUserDetailByIdAPI(id)
      // console.log(res)
      this.$refs.roleDialog.roleIdArr = res.data.roleIds
    },
    // 关闭分配角色弹框
    cancleDialog() {
      this.showRoleDialog = false
      // 优化
      this.$refs.roleDialog.roleIdArr = []
    },
    // 分配角色里点击确定
    async confirmFn(roleIdArr) {
      const res = await assignRolesAPI({
        id: this.employeeId,
        roleIds: roleIdArr
      })
      if (!res.success) return this.$message.error(res.message)
      // console.log(res)
      if (res.success) this.$message.success(res.message)
      this.showRoleDialog = false
      this.getEmployeeListFn()
    }
  }
}
</script>

<style lang="scss" scoped>
.page-tools {
  display: flex;
  justify-content: space-between;
  align-items: center;

  .tips {
    line-height: 34px;
    padding: 0px 15px;
    border-radius: 5px;
    border: 1px solid rgba(145, 213, 255, 1);
    background: rgba(230, 247, 255, 1);

    i {
      margin-right: 10px;
      color: #409eff;
    }
  }
}
.staffPhoto {
  width: 100px;
  height: 100px;
  border-radius: 50%;
}
</style>
